//
//  STNativeAdmobObject.swift
//  iPhone
//
//  Created by Toj on 3/30/23.
//

import Foundation
import GoogleMobileAds

class STNativeAdmobObject: STAdmobObject {
    
    /* 广告对象 */
    typealias AdObject = UIImage
    
    /* 广告展示开始时间: 用来报数展示多长时间 */
    private var startTime: CFAbsoluteTime = 0
    
    /* 广告状态 */
    private var loadState: STAdmobAdState = .normal
    
    /* 预加载广告数据: 用来预加载 广告平台对象 */
    private var _preloadAdModel: STAdmobModel?
    /* 预加载广告对象: 借助广告数据加载后的 广告平台对象 */
    private var _preloadedGAd: AdObject?
    
    /* 加载广告数据: 用来加载 广告平台对象 */
    private var _admobModel: STAdmobModel?
    /* 加载广告对象: 借助广告数据加载后的 广告平台对象 */
    private var _loadedGAd: AdObject? { didSet {
        guard let _ = _loadedGAd else {
            loadState.remove([.loading,.loaded, .showing, .showed])
            return
        }
        
        loadState.remove(.loading)
        loadState.insert(.loaded)
    } }
}

// MARK: - 广告协议
extension STNativeAdmobObject: STAdmobProtocol  {
    
    var delegate: STAdmobObjectDelegate? {
        get { return _delegate }
        set { _delegate = newValue }
    }
    
    /*
     * 读取是否有 预加载完成的 广告对象
     */
    func isPreparedAd(admobModel: STAdmobModel) -> Bool {
        // _preloadedGAd = 读取缓存
        let isPrepared = _preloadedGAd != nil
        if isPrepared {
            responseLoadAd(admobModel: admobModel, adObject: _preloadedGAd, error: nil)
            _preloadedGAd = nil
        }
        return isPrepared
    }
    
    /* 预加载 广告对象 */
    func preloadCacheAd(admobModel: STAdmobModel) {
        print("-->toj: 原生 准备预加载广告")
        
        _preloadAdModel = admobModel
        
        print("-->toj: 原生 预加载广告")
        requestLoadAd(admobModel: admobModel) { [weak self] ad, error in
            self?.responsePreloadAd(admobModel: admobModel, adObject: ad, error: error)
            print("-->toj: 原生 预加载广告 完成")
        }
    }
    
    /* 更新预加载 广告数据 并且预加载 广告对象 */
    func replacePreloadCacheAd(admobModel: STAdmobModel, completion: ((Bool) -> Void)?) {
        print("-->toj: 原生 更新预加载广告")
        
        _preloadAdModel = admobModel
        
        loadState.insert(.preloading)
        print("-->toj: 原生 更新后预加载广告")
        requestLoadAd(admobModel: admobModel) { [weak self] ad, error in
            self?.responsePreloadAd(admobModel: admobModel, adObject: ad, error: error)
            let isSuccess = ad != nil
            completion?(isSuccess)
        }
    }
    /*
     * 预加载 广告对象,
     * 有预加载 广告对象: 待展示
     * 无预加载 广告对象: 加载 广告对象, 加载完后缓存广告对象 待展示
     */
    func preloadAd(admobModel: STAdmobModel, completion: ((Bool) -> Void)?) {
        print("-->toj: 原生 准备预加载广告")
        let prematerials = _preloadAdModel?.materials
        let materials = admobModel.materials
        guard _preloadedGAd != nil && prematerials == materials else {
            print("-->toj: 原生 无 预缓存对象, 开始缓存广告对象")
            preloadCacheAd(admobModel: admobModel)
            completion?(false)
            return
        }
        
        print("-->toj: 原生 有 预缓存对象")
        if loadState.isLoading { return }
        loadState.insert(.loading)
        
        print("-->toj: 原生 有 预缓存对象, 待展示")
        // 更新最新广告对象
        // 保存广告数据
        responseLoadAd(admobModel: admobModel, adObject: _preloadedGAd, error: nil)
        // 清空预缓存对象
        _preloadedGAd = nil
        completion?(true)
    }
    
    /* 加载新广告对象 */
    func loadAd(admobModel: STAdmobModel, completion: ((Bool) -> Void)?) {
        print("-->toj: 原生 准备加载全新广告")
        if loadState.isLoading {
            completion?(false)
            return
        }
        loadState.insert(.loading)
        print("-->toj: 原生 开始加载最新广告")
        requestLoadAd(admobModel: admobModel) { [weak self] ad, error in
            self?.responseLoadAd(admobModel: admobModel, adObject: ad, error: error)
            let isSuccess = ad != nil
            completion?(isSuccess)
        }
    }
    
    /* 展示 广告对象 */
    func presentAd(from vc: UIViewController) {
        print("-->toj: 原生 展示")
        let child = STFullScreenAdController()
        child.ls_delegate = self
        child.imageView.image = _loadedGAd
        child.admobModel = _admobModel
        vc.addChild(child)
        vc.view.addSubview(child.view)
        child.view.frame = vc.view.bounds
    }
}

private extension STNativeAdmobObject {
    
    /* 加载广告 */
    func requestLoadAd(admobModel: STAdmobModel,
                       completion: @escaping ((_ ad: AdObject?, _ error: Error?)->Void)) {
        print("-->toj: 原生 加载广告对象")
        
        // loadImage
        completion("kuanping024".img_resource, nil)
    }
    
    /* 预加载广告回调 */
    func responsePreloadAd(admobModel: STAdmobModel,
                           adObject: AdObject?,
                           error: Error?) {
        print("-->toj: 原生 预加载广告 响应")
        guard admobModel.materials == _preloadAdModel?.materials
        else { return }
        
        _preloadedGAd = adObject
        if let error = error {
            print("-->toj: 原生 预加载广告 响应 失败: \(error.localizedDescription). materials: \(admobModel.materials)")
            return
        }
        print("-->toj: 原生 预加载广告 响应 成功")
    }
    
    /* 加载广告回调 */
    func responseLoadAd(admobModel: STAdmobModel,
                        adObject: AdObject?,
                        error: Error?) {
        _loadedGAd = adObject
        
        if let error = error {
            print("-->toj: 原生 加载失败: \(error.localizedDescription). materials: \(admobModel.materials)")
            fullScreenAdControllerDidFail(error: error)
            return
        }
        
        _admobModel = admobModel
        print("-->toj: 原生 加载成功")
    }
    
    /* 清除广告 */
    func clearAd() {
        print("-->toj: 原生 清除广告")
        _loadedGAd = nil
    }
}

extension STNativeAdmobObject: STFullScreenAdControllerDelegate {
    
    // 广告展示失败
    func fullScreenAdControllerDidFail(error: Error) {
        print("-->toj: 原生 广告展示失败")
        delegate?.admobObject(self, admobModel: _admobModel, didFailToPresentFullScreenContent: error)
        clearAd()
    }
    
    // 广告展示
    func fullScreenAdControllerDidPresent(_ viewContrller: STFullScreenAdController) {
        print("-->toj: 原生 广告展示成功")
        
        startTime = CFAbsoluteTimeGetCurrent()
        loadState.insert(.showing)
        
        delegate?.admobObjectDidPresentContent(self, admobModel: _admobModel)
    }
    
    // 广告即将退出
    func fullScreenAdControllerWillDismiss(_ viewContrller: STFullScreenAdController) {
        print("-->toj: 原生 广告即将消失")
        let endTime = CFAbsoluteTimeGetCurrent()
        let showedTime = endTime - startTime
        // print("-->toj: 原生 endTime:\(endTime)")
        // print("-->toj: 原生 startTime:\(startTime)")
        print("-->toj: 原生 time:\(showedTime)")
        delegate?.admobObjectWillDismissComplete(self, admobModel: _admobModel, showedTime: showedTime)
    }
    
    // 广告退出
    func fullScreenAdControllerDidDismiss(_ viewContrller: STFullScreenAdController) {
        print("-->toj: 原生 广告消失")
        
        delegate?.admobObjectDidDismissComplete(self, admobModel: _admobModel)
        clearAd()
        
        viewContrller.view.removeFromSuperview()
        viewContrller.removeFromParent()
    }
    
    // 广告点击
    func fullScreenAdControllerDidTapAd(_ viewContrller: STFullScreenAdController) {
        print("-->toj: 原生 广告点击")
        delegate?.admobObjectDidRecordClick(self, admobModel: _admobModel)
    }
}
